﻿using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace MapFormsApp.Services
{
    /// <summary>
    /// 地图显示控制核心类（封装MapControl操作）
    /// </summary>
    public class MapManager : IDisposable
    {
        private readonly IMapControl3 _mapControl;
        private IMap _map;
        private ISpatialReference _mapSpatialRef;

        public IMap Map => _map;
        #region 初始化与配置
        /// <summary>
        /// 构造函数（绑定地图控件）
        /// </summary>
        public MapManager(IMapControl3 mapControl)
        {
            _mapControl = mapControl ?? throw new ArgumentNullException(nameof(mapControl));
            _map = _mapControl.Map;
            //_mapSpatialRef = GetMapSpatialReference();
        }

        /// <summary>
        /// 加载地图文档（MXD文件）
        /// </summary>
        public void LoadMapDocument(string mxdPath)
        {
            if (!System.IO.File.Exists(mxdPath))
                throw new ArgumentException("地图文档不存在");

            // 1. 加载地图文档
            _mapControl.LoadMxFile(mxdPath);
            _map = _mapControl.Map;
            
            //_mapSpatialRef = GetMapSpatialReference();
            RefreshMap();
        }
        #endregion

        #region 图层管理
        /// <summary>
        /// 添加要素类图层（自动投影）
        /// </summary>
        public void AddFeatureLayer(IFeatureClass featureClass, string layerName = null)
        {
            if (featureClass == null) return;

            // 确保坐标系一致
            IGeoDataset geoDataset = (IGeoDataset)featureClass;
            //if (!geoDataset.SpatialReference.IsSame(_mapSpatialRef))
            //{
            //    featureClass = ProjectFeatureClass(featureClass, _mapSpatialRef);
            //}

            IFeatureLayer featureLayer = new FeatureLayerClass
            {
                FeatureClass = featureClass,
                Name = string.IsNullOrEmpty(layerName) ? featureClass.AliasName : layerName
            };

            _map.AddLayer(featureLayer);
            SetLayerVisibility(featureLayer, true);
            RefreshMap();
        }

        /// <summary>
        /// 按名称查找图层
        /// </summary>
        public ILayer FindLayerByName(string layerName)
        {
            for (int i = 0; i < _map.LayerCount; i++)
            {
                ILayer layer = _map.get_Layer(i);
                if (layer.Name.Equals(layerName, StringComparison.OrdinalIgnoreCase))
                {
                    return layer;
                }
            }
            return null;
        }

        /// <summary>
        /// 设置图层可见性
        /// </summary>
        public void SetLayerVisibility(ILayer layer, bool visible)
        {
            if (layer == null) return;

            layer.Visible = visible;
            RefreshView(esriViewDrawPhase.esriViewGeography);
        }

        /// <summary>
        /// 设置导航路径
        /// </summary>
        /// <param name="routeGeometry"></param>
        /// <param name="layerName"></param>
        public void AddRouteLayer(IPolyline routeGeometry, string layerName = "导航路径")
        {
            // 创建临时要素类
            IFeatureClass tempFC = CreateTempFeatureClass(
                esriGeometryType.esriGeometryPolyline,
                routeGeometry.SpatialReference
            );

            // 将几何对象存入要素类
            using (ESRI.ArcGIS.ADF.ComReleaser cr = new ESRI.ArcGIS.ADF.ComReleaser())
            {
                IFeature feature = tempFC.CreateFeature();
                cr.ManageLifetime(feature);
                feature.Shape = routeGeometry;
                feature.Store();
            }

            // 创建图层并添加到地图
            IFeatureLayer routeLayer = new FeatureLayerClass();
            routeLayer.FeatureClass = tempFC;
            routeLayer.Name = layerName;

            // 设置符号样式
            ISimpleLineSymbol lineSymbol = new SimpleLineSymbolClass
            {
                Style = esriSimpleLineStyle.esriSLSSolid,
                Color = new RgbColorClass { Red = 255 }, // 红色
                Width = 3
            };

            ((IGeoFeatureLayer)routeLayer).Renderer = new SimpleRendererClass
            {
                Symbol = (ISymbol)lineSymbol
            };

            _map.AddLayer(routeLayer);
            RefreshMap();
        }
        /// <summary>
        /// 辅助方法
        /// </summary>
        /// <param name="geometryType"></param>
        /// <param name="spatialRef"></param>
        /// <returns></returns>
        private IFeatureClass CreateTempFeatureClass(esriGeometryType geometryType, ISpatialReference spatialRef)
        {
            IWorkspace workspace = ((IDataset)_map).Workspace;
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;

            // 定义字段
            IFields fields = new FieldsClass();
            IFieldsEdit fieldsEdit = (IFieldsEdit)fields;

            // 添加ObjectID字段
            IField oidField = new FieldClass();
            IFieldEdit oidFieldEdit = (IFieldEdit)oidField;
            oidFieldEdit.Name_2 = "OBJECTID";
            oidFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
            fieldsEdit.AddField(oidField);

            // 添加几何字段
            IGeometryDef geometryDef = new GeometryDefClass();
            IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
            geometryDefEdit.GeometryType_2 = geometryType;
            geometryDefEdit.SpatialReference_2 = spatialRef;

            IField shapeField = new FieldClass();
            IFieldEdit shapeFieldEdit = (IFieldEdit)shapeField;
            shapeFieldEdit.Name_2 = "Shape";
            shapeFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
            shapeFieldEdit.GeometryDef_2 = geometryDef;
            fieldsEdit.AddField(shapeField);

            return featureWorkspace.CreateFeatureClass(
                "TempRoute_" + Guid.NewGuid().ToString("N"),
                fields,
                null, null, esriFeatureType.esriFTSimple,
                "Shape",
                ""
            );
        }
        #endregion

        #region 坐标转换
        /// <summary>
        /// 屏幕坐标转地图坐标
        /// </summary>
        public IPoint ScreenToMap(int x, int y)
        {
            return _mapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
        }

        /// <summary>
        /// 地图坐标转屏幕坐标
        /// </summary>
        public void MapToScreen(IPoint mapPoint, out int x, out int y)
        {
            IDisplayTransformation displayTrans = _mapControl.ActiveView.ScreenDisplay.DisplayTransformation;
            displayTrans.FromMapPoint(mapPoint, out x, out y);
        }
        #endregion

        #region 地图操作
        /// <summary>
        /// 缩放到全图范围
        /// </summary>
        public void ZoomToFullExtent()
        {
            IActiveView activeView = _mapControl.ActiveView;
            activeView.Extent = activeView.FullExtent;
            activeView.Refresh();
        }

        /// <summary>
        /// 缩放到指定几何范围
        /// </summary>
        public void ZoomToGeometry(IGeometry geometry)
        {
            if (geometry == null) return;

            IEnvelope envelope = geometry.Envelope;
            IActiveView activeView = _mapControl.ActiveView;
            activeView.Extent = envelope;
            activeView.Refresh();
        }

        /// <summary>
        /// 清除所有临时图层
        /// </summary>
        public void ClearTempLayers()
        {
            List<ILayer> layersToRemove = new List<ILayer>();

            for (int i = 0; i < _map.LayerCount; i++)
            {
                ILayer layer = _map.get_Layer(i);
                if (layer.Name.StartsWith("Temp_"))
                {
                    layersToRemove.Add(layer);
                }
            }

            foreach (ILayer layer in layersToRemove)
            {
                _map.DeleteLayer(layer);
            }
            RefreshMap();
        }
        #endregion

        #region 渲染与符号化
        /// <summary>
        /// 应用简单符号渲染
        /// </summary>
        public void ApplySimpleRenderer(IFeatureLayer layer, IColor color, int size = 5)
        {
            ISimpleRenderer renderer = new SimpleRendererClass();
            ISimpleMarkerSymbol symbol = new SimpleMarkerSymbolClass
            {
                Style = esriSimpleMarkerStyle.esriSMSCircle,
                Color = color,
                Size = size
            };
            renderer.Symbol = (ISymbol)symbol;
            ((IGeoFeatureLayer)layer).Renderer = (IFeatureRenderer)renderer;
            RefreshView(esriViewDrawPhase.esriViewGeography);
        }

        /// <summary>
        /// 高亮选择要素
        /// </summary>
        public void HighlightSelection(IFeatureLayer layer, IColor highlightColor)
        {
            //ISelectionRenderer selectionRenderer = new BasicSelectionRendererClass();
            //ISimpleFillSymbol fillSymbol = new SimpleFillSymbolClass
            //{
            //    Color = highlightColor,
            //    Outline = new SimpleLineSymbolClass { Color = highlightColor, Width = 2 }
            //};
            //selectionRenderer.Symbol = fillSymbol;
            //((IFeatureSelection)layer).SelectionRenderer = selectionRenderer;
            //RefreshView(esriViewDrawPhase.esriViewGeography);
        }
        #endregion

        #region 底层工具方法
        private ISpatialReference GetMapSpatialReference()
        {
            IGeoDataset geoDataset = (IGeoDataset)_map;
            return geoDataset.SpatialReference;
        }

        private IFeatureClass ProjectFeatureClass(IFeatureClass sourceClass, ISpatialReference targetSpatialRef)
        {
            IGeoProcessor2 gp = new GeoProcessorClass();
            IVariantArray parameters = new VarArrayClass();

            parameters.Add(sourceClass);
            parameters.Add(targetSpatialRef);
            parameters.Add("PRESERVE_SHAPE");

            IGeoDataset result = gp.Execute("Project_management", parameters, null) as IGeoDataset;
            return (IFeatureClass)result;
        }

        private void RefreshView(esriViewDrawPhase drawPhase = esriViewDrawPhase.esriViewAll)
        {
            _mapControl.ActiveView.PartialRefresh(drawPhase, null, null);
        }

        private void RefreshMap()
        {
            _mapControl.Refresh();
            _mapControl.ActiveView.Refresh();
        }
        #endregion

        #region 资源清理
        private bool _disposed = false;

        public void Dispose()
        {
            if (_disposed) return;

            //if (_mapControl != null)
            //{
            //    _mapControl.Map = null;
            //    Marshal.ReleaseComObject(_mapControl);
            //}
            _disposed = true;
            GC.SuppressFinalize(this);
        }

        ~MapManager() => Dispose();
        #endregion
    }
}